/* 
 * File:   Repositorio.cpp
 * Author: gabilan
 * 
 * Created on 24 de mayo de 2013, 19:33
 */

#include "common_Repositorio.h"
#include "common_FileUtils.h"
using namespace TP::Archivos;

Repositorio::Repositorio(){
    _path = "";
}

Repositorio::Repositorio (const string &pPath){
    _path = pPath;
}

Repositorio::~Repositorio() {
    if(!this->lista_archs.empty())
    {
        SetRepoItem::iterator it;
        for(it = this->lista_archs.begin(); it != this->lista_archs.end();it++)
        {
            RepoItem * r = *it;
            delete(r);
        }
        this->lista_archs.clear();
    }
}

bool Repositorio::ExisteRepoItem(const string & filename){
    SetRepoItem::iterator it = this->lista_archs.begin();
    bool encontrado = false;
    while(!encontrado && it != this->lista_archs.end())
    {
        RepoItem * rep = *it;
        if(rep->GetFilename() == filename) encontrado = true;
        else it++;
    }
    return encontrado; 
}

RepoItem* Repositorio::GetRepoItemByPath(const string & path){
    SetRepoItem::iterator it = this->lista_archs.begin();
    bool encontrado = false;
    while(!encontrado && it != this->lista_archs.end())
    {
        RepoItem * rep = *it;
        if(rep->GetFilePath() == path) encontrado = true;
        else it++;
    }
    if(encontrado) return *it;
    else return NULL;
}

RepoItem* Repositorio::GetRepoItemByFilename(const string & filename){    
    SetRepoItem::iterator it = this->lista_archs.begin();
    bool encontrado = false;
    while(!encontrado && it != this->lista_archs.end())
    {
        RepoItem * rep = *it;
        if(rep-> GetFilename() == filename) encontrado = true;
        else it++;
    }
    if(encontrado) return *it;
    else return NULL;
}

/* IniciarAPartirDeDirectorio:
 *      Inicializa la estructura de repositorio a partir del directorio que se
 * especifíca por parámetro.  Para todo archivo contenido en el directorio, 
 * computa el nombre, la ruta, la ruta completa y la lista de hashes asociadas 
 * almacenando y disponibilizando dicha información.
 */
bool Repositorio::IniciarAPartirDeDirectorio (const string & pRutaDirectorio) throw (Excepcion &){
    
    FileUtils fileUtils;
    
    if (!fileUtils.DirectorioExistente(pRutaDirectorio))
    {
        return false;
    }
    
    _path = pRutaDirectorio;
    
    // Se lee la lista de archivos contenida en el directorio.
    LNombreArchivo archivos;
    fileUtils.ObtenerNombreArchivos(pRutaDirectorio, archivos);
    
    // Para todo archivo contenido en el direcotrio =>

    LNombreArchivo::iterator it = archivos.begin();
    while (it < archivos.end())
    {
        // Se declara el archivo en el repositorio.
        RepoItem* item = new RepoItem();
        
        item->SetFilePath(pRutaDirectorio);
        item->SetFilename(*it);
        
        // Se computan los hashes que definen al archivo.
        ComputarHashesDeArchivo (item);
        
        this->AgregarRepoItem(item);
        
        it++;
    }
    return true;
}

bool Repositorio::IniciarAPartirDeArchivoConfiguracion (const string &pRutaArchivoConfiguracion)throw (Excepcion&){
    return false;
}

void Repositorio::ComputarHashesDeArchivo (RepoItem* pItem) throw (Excepcion &){
    
    if (NULL == pItem)
    {
        throw Excepcion ("No se puede computar los hashes del archivo.  no se especifica un item.");
    }
    
    FileUtils fileUtils;
    size_t cantidadChunks = fileUtils.CalcularCantidadChunks(pItem->GetRutaCompletaArchivo());
    
    for (size_t i = 0; i < cantidadChunks; i++)
    {
        pItem->AddHash(fileUtils.GetHash(pItem->GetRutaCompletaArchivo(), i));
    }
}